package com.party.web.biz.charge;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.party.common.utils.BigDecimalUtils;
import com.party.common.utils.DateUtils;
import com.party.common.utils.StringUtils;
import com.party.core.model.YesNoStatus;
import com.party.core.model.charge.*;
import com.party.core.model.member.MemberGroup;
import com.party.core.model.order.OrderForm;
import com.party.core.model.order.OrderFormSubInfo;
import com.party.core.model.order.OrderStatus;
import com.party.core.model.order.OrderType;
import com.party.core.model.system.RoleType;
import com.party.core.model.system.SysRole;
import com.party.core.service.charge.IPackageMemberService;
import com.party.core.service.charge.IPackagePrivilegeService;
import com.party.core.service.charge.IPackageService;
import com.party.core.service.charge.IPrivilegeService;
import com.party.core.service.member.IMemberGroupService;
import com.party.core.service.order.IOrderFormService;
import com.party.core.service.order.IOrderFormSubInfoService;
import com.party.core.service.system.ISysRoleService;
import com.party.web.biz.order.QueryBizService;
import com.party.web.biz.serviceOrder.ServiceOrderBizService;
import com.party.web.jms.publisher.service.IOrderCancelPubulisherService;
import com.party.web.utils.RealmUtils;
import com.party.web.web.dto.output.charge.PackagePrivilegeOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * 套餐业务
 *
 * @author Administrator
 * @date 2017/7/27 0027 14:50
 */
@Service
public class PackageBizService {
    @Autowired
    private IPackageMemberService packageMemberService;
    @Autowired
    private IPackageService packageService;
    @Autowired
    private ISysRoleService sysRoleService;
    @Autowired
    private IPrivilegeService privilegeService;
    @Autowired
    private IPackagePrivilegeService packagePrivilegeService;
    @Autowired
    private IMemberGroupService memberGroupService;
    @Autowired
    private IOrderFormService orderFormService;
    @Autowired
    private QueryBizService queryBizService;
    @Autowired
    private IOrderCancelPubulisherService orderCancelPubulisherService;
    @Autowired
    private IOrderFormSubInfoService orderFormSubInfoService;
    @Autowired
    private ServiceOrderBizService serviceOrderBizService;

    Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 获取用户所拥有的角色的最高套餐关系
     *
     * @param memberId
     * @param sysRoles
     * @return
     */
    public PackageMember getPackageMember(String memberId, List<SysRole> sysRoles) {
        Map<String, Object> params = Maps.newHashMap();

        params.put("type1", ProductType.PACKAGE_TYPE.getCode());
        params.put("type2", ProductType.SYSTEM_TYPE.getCode());


        // 获取购买的最高等级套餐
        PackageMember packageMember = packageMemberService.getMaxPackageRole(new PackageMember("", memberId), params);
        if (packageMember != null) {
            return packageMember;
        } else {
            if (sysRoles == null) {
                sysRoles = Lists.newArrayList();
            }
            params = Maps.newHashMap();
            params.put("type", RoleType.PARTNER_ROLE.getCode());
            params.put("memberId", memberId);
            sysRoles.addAll(sysRoleService.getRoleByMemberId(params));
            List<ProductPackage> newPackges = getProductPackages(sysRoles, ProductType.PACKAGE_TYPE.getCode());
            if (newPackges.size() > 0) {
                Collections.sort(newPackges, new Comparator<ProductPackage>() {
                    @Override
                    public int compare(ProductPackage o1, ProductPackage o2) {
                        return o1.getLevel() > o2.getLevel() ? -1 : 1;
                    }
                });

                packageMember = new PackageMember();
                packageMember.setLevelId(newPackges.get(0).getId());
                packageMember.setSysRoleId(newPackges.get(0).getSysRoleId());
                return packageMember;
            }
            return null;
        }
    }

    /**
     * 获取角色对应的套餐
     *
     * @param sysRoles 角色集合
     * @param type     套餐类型
     * @return
     */
    private List<ProductPackage> getProductPackages(List<SysRole> sysRoles, Integer type) {
        ProductPackage t = new ProductPackage();
        t.setType(type);
        List<ProductPackage> packages = packageService.list(t);
        List<ProductPackage> newPackges = new ArrayList<ProductPackage>();
        for (ProductPackage p : packages) {
            boolean flag = false;
            for (SysRole r : sysRoles) {
                if (p.getSysRoleId().equals(r.getId())) {
                    flag = true;
                    break;
                }
            }
            if (flag) {
                newPackges.add(p);
            }
        }
        return newPackges;
    }

    /**
     * 获取用户所拥有角色对应的模块套餐关系
     *
     * @param memberId 用户id
     * @return
     */
    public List<PackageMember> getPackaeMemberModule(String memberId) {
        Map<String, Object> params = Maps.newHashMap();
        params.put("type", RoleType.BUSINESS_ROLE.getCode());
        params.put("memberId", memberId);
        List<SysRole> sysRoles = sysRoleService.getRoleByMemberId(params);

        params = Maps.newHashMap();
        params.put("type", ProductType.MODULE_TYPE.getCode());
        List<PackageMember> packageMembers = packageMemberService.newListPage(new PackageMember("", memberId), params);
        if (packageMembers.size() < sysRoles.size()) {
            List<ProductPackage> newPackges = getProductPackages(sysRoles, ProductType.MODULE_TYPE.getCode());
            if (newPackges.size() > 0) {
                packageMembers = Lists.newArrayList();
                for (ProductPackage p : newPackges) {
                    PackageMember pMember = new PackageMember();
                    pMember.setLevelId(p.getId());
                    pMember.setSysRoleId(p.getSysRoleId());
                    packageMembers.add(pMember);
                }
            }
        }
        return packageMembers;
    }

    /**
     * 获取用户所购买的短信套餐
     *
     * @param memberId
     * @return
     */
    public List<PackageMember> getPackageMemberSms(String memberId) {
        Map<String, Object> params = Maps.newHashMap();
        params.put("type", ProductType.SMS_PACKAGE_TYPE.getCode());
        List<PackageMember> packageMembers = packageMemberService.newListPage(new PackageMember("", memberId), params);
        return packageMembers;
    }

    /**
     * 获取所有权限对应的套餐值
     *
     * @param productPackages
     * @return
     */
    public List<PackagePrivilegeOutput> getPackagePrivilegeList(List<ProductPackage> productPackages) {
        List<PackagePrivilegeOutput> pOutputs = Lists.newArrayList();
        List<ProductPrivilege> privileges = privilegeService.list(new ProductPrivilege("0"));
        for (ProductPrivilege p : privileges) {
            List<PackagePrivilegeOutput> cOutputs = Lists.newArrayList();
            for (ProductPrivilege c : p.getChildrens()) {
                List<Map<String, Object>> showMap = Lists.newArrayList();
                for (ProductPackage aPackage : productPackages) {
                    PackagePrivilege pp = packagePrivilegeService.getUnique(new PackagePrivilege(aPackage.getId(), c.getId()));
                    Map<String, Object> resultClazz = Maps.newHashMap();
                    resultClazz.put("packageId", aPackage.getId());
                    if (pp != null) {
                        if (StringUtils.isEmpty(pp.getParamValue())) {
                            resultClazz.put("paramValue", true);
                        } else {
                            resultClazz.put("paramValue", pp.getParamValue());
                        }
                    }
                    showMap.add(resultClazz);
                }
                PackagePrivilegeOutput cOutput = new PackagePrivilegeOutput();
                cOutput.setResultClazzes(showMap);
                cOutput.setPrivilege(c);
                cOutputs.add(cOutput);
            }

            PackagePrivilegeOutput pOutput = new PackagePrivilegeOutput();
            pOutput.setPrivilege(p);
            pOutput.setChildrens(cOutputs);
            pOutputs.add(pOutput);
        }
        return pOutputs;
    }

    /**
     * 获取套餐对应的权限
     *
     * @param packageId 套餐id
     * @param code      权限code
     * @return
     */
    public PackagePrivilege getPackagePrivilege(String packageId, String code) {
        Map<String, Object> params = Maps.newHashMap();
        params.put("packageId", packageId);
        params.put("code", code);
        PackagePrivilege packagePrivilege = packagePrivilegeService.findByPackage(params);
        return packagePrivilege;
    }

    /**
     * 购买
     *
     * @param paymentWay 支付方式
     * @param packageId  套餐id
     * @param quantity   数量
     * @return
     */
    @Transactional
    public OrderForm buyOrder(Integer paymentWay, String packageId, Integer quantity) {
        OrderForm orderForm = null;

        ProductPackage productPackage = packageService.get(packageId);
        Float payment = productPackage.getPrice();
        Float newPayment = payment;
        if (null != quantity) {
            BigDecimal b1 = new BigDecimal(Double.toString(payment));
            BigDecimal b2 = new BigDecimal(Double.toString(quantity));
            newPayment = BigDecimalUtils.round(b1.multiply(b2).floatValue(), 2);
        }


        // 查看这个套餐当天是否产生未支付的订单，如有则返回；否则生成新订单
        String memberId = RealmUtils.getCurrentUser().getId();
        MemberGroup member = memberGroupService.get(memberId);
        MemberGroup adminMember = memberGroupService.findByUserName("admin");

        OrderForm t = new OrderForm();
        t.setMemberId(memberId);
        t.setGoodsId(packageId);
        Map<String, Object> params = Maps.newHashMap();
        Date sd = new Date();
        String std = DateUtils.formatDate(sd, "yyyy-MM-dd") + " 00:00:00";
        params.put("startDate", std);
        String end = DateUtils.formatDate(sd, "yyyy-MM-dd") + " 23:59:59";
        params.put("endDate", end);

        Set<Integer> orderStatus = Sets.newHashSet();
        orderStatus.add(OrderStatus.ORDER_STATUS_OTHER.getCode());
        orderStatus.add(OrderStatus.ORDER_STATUS_TO_BE_PAID.getCode());
        params.put("orderStatus", orderStatus);
        orderForm = orderFormService.getOrderByCondition(t, params);
        if (orderForm != null) {
            Boolean flag = queryBizService.checkOrderTradeStatus(newPayment, orderForm);
            if (flag == null || flag) {
                orderForm = new OrderForm();
            }
        }

        if (orderForm == null) {
            orderForm = new OrderForm();
        }
        orderForm.setStatus(OrderStatus.ORDER_STATUS_TO_BE_PAID.getCode());
        orderForm.setPayment(newPayment);
        orderForm.setLinkman(member.getRealname());
        orderForm.setPhone(member.getMobile());
        orderForm.setPaymentWay(paymentWay);
        orderForm.setUpdateDate(new Date());
        String title = appendTitle(productPackage, quantity);
        orderForm.setTitle(title);


        if (StringUtils.isEmpty(orderForm.getId())) {
            orderForm.setCreateBy(memberId);
            orderForm.setUpdateBy(memberId);
            orderForm.setMemberId(memberId);
            orderForm.setGoodsId(packageId);
            orderForm.setInitiatorId(adminMember.getId());
            orderForm.setPayment(newPayment);
            orderForm.setIsPay(YesNoStatus.NO.getValue());
            orderForm.setUnit(1);
            orderForm.setType(OrderType.ORDER_LEVEL.getCode());
            orderForm.setStatus(OrderStatus.ORDER_STATUS_TO_BE_PAID.getCode());
            orderFormService.insert(orderForm);

            try {
                OrderFormSubInfo formSubInfo = new OrderFormSubInfo();
                formSubInfo.setOrderId(orderForm.getId());
                if (null != member) {
                    formSubInfo.setAuthorLogo(member.getLogo());
                    formSubInfo.setAuthorName(member.getRealname());
                }
                if (null != adminMember) {
                    formSubInfo.setInitiatorLogo(adminMember.getLogo());
                    formSubInfo.setInitiatorName(adminMember.getRealname());
                }
                orderFormSubInfoService.insert(formSubInfo);
            } catch (Exception e) {
                logger.error("保存订单附属信息异常", e);
            }
        } else {
            orderFormService.update(orderForm);
        }
        this.insertOrUpdatePackageMember(orderForm, memberId, productPackage, quantity);

        try {
            orderCancelPubulisherService.send(orderForm.getId());
        } catch (Exception e) {
            logger.error("取消超时待支付订单异常", e);
        }

        return orderForm;
    }

    /**
     * 处理套餐和用户的关系
     *
     * @param orderForm      订单
     * @param memberId       用户id
     * @param productPackage 套餐
     * @param quantity       数量
     */
    public void insertOrUpdatePackageMember(OrderForm orderForm, String memberId, ProductPackage productPackage, Integer quantity) {
        PackageMember packageMember = packageMemberService.findByOrderId(orderForm.getId());
        if (packageMember == null) {
            packageMember = new PackageMember();
            packageMember.setPayStatus(1);
            packageMember.setOrderId(orderForm.getId());
            packageMember.setMemberId(memberId);
            packageMember.setLevelId(productPackage.getId());
            packageMember.setStatus(2);
        }
        packageMember.setPackageName(productPackage.getName());
        packageMember.setPrice(orderForm.getPayment());
        packageMember.setPayWay(orderForm.getPaymentWay());
        if (productPackage.getType().equals(ProductType.SMS_PACKAGE_TYPE.getCode())) {
            packageMember.setSmsSource(2);
            if (productPackage.getIsUserDefined().equals(YesNoStatus.YES.getCode())) {
                packageMember.setQuantity(productPackage.getQuantity());
            } else {
                packageMember.setQuantity(quantity);
            }
        } else if (productPackage.getType().equals(ProductType.PACKAGE_TYPE.getCode())
                || productPackage.getType().equals(ProductType.MODULE_TYPE.getCode())) { // 套餐、模块，保存用户等级，更改用户角色
            Map<String, Date> resultMap = calculateDate(productPackage, null);
            Date startTime = resultMap.get("startTime");
            Date endTime = resultMap.get("endTime");
            packageMember.setStartTime(startTime);
            packageMember.setEndTime(endTime);
            packageMember.setSysRoleId(productPackage.getSysRoleId());
        }
        if (StringUtils.isEmpty(packageMember.getId())) {
            packageMemberService.insert(packageMember);
        } else {
            packageMemberService.update(packageMember);
        }
    }

    /**
     * 拼接订单名称
     *
     * @param productPackage
     * @return
     */
    public String appendTitle(ProductPackage productPackage, Integer quantity) {
        String title = productPackage.getPrice() > 0.0f ? "购买" : "免费领取";
        if (productPackage.getType().equals(ProductType.SMS_PACKAGE_TYPE.getCode())) {
            if (productPackage.getIsUserDefined().equals(YesNoStatus.YES.getCode())) {
                title += quantity + "条短信";
            } else {
                title += productPackage.getQuantity() + "条短信";
            }
        } else if (ProductType.SYSTEM_TYPE.getCode() == productPackage.getType()) {
            String systemName = "";
            if (ProductPackage.SYSTEM_TYPE_SQ == productPackage.getSystemType()) {
                systemName += "社群";
            } else if (ProductPackage.SYSTEM_TYPE_ZC == productPackage.getSystemType()) {
                systemName += "众筹";
            }
            title += productPackage.getName() + systemName + "系统";
        } else {
            title += productPackage.getName() + "功能";
            if (productPackage.getUnit().equals(ProductPackage.UNIT_HALF_YEAR)) {
                title += productPackage.getUnit();
            } else {
                title += ("一" + productPackage.getUnit());
            }
        }
        return title;
    }

    /**
     * 计算时间
     *
     * @param productPackage
     * @param packageMember
     * @return
     */
    public Map<String, Date> calculateDate(ProductPackage productPackage, PackageMember packageMember) {
        Date startTime = null;
        Date endTime = null;
        Calendar calendar = Calendar.getInstance();
        startTime = calendar.getTime(); // 开始时间
        if (packageMember != null) {
            calendar.setTime(packageMember.getEndTime());
        }
        if (productPackage.getUnit().equals(ProductPackage.UNIT_MONTH)) {
            calendar.add(Calendar.MONTH, 1);
        } else if (productPackage.getUnit().equals(ProductPackage.UNIT_QUARTER)) {
            calendar.add(Calendar.MONTH, 3);
        } else if (productPackage.getUnit().equals(ProductPackage.UNIT_HALF_YEAR)) {
            calendar.add(Calendar.MONTH, 6);
        } else if (productPackage.getUnit().equals(ProductPackage.UNIT_YEAR)) {
            calendar.add(Calendar.YEAR, 1);
        }
        endTime = calendar.getTime(); // 结束时间

        Map<String, Date> result = Maps.newHashMap();
        result.put("startTime", startTime);
        result.put("endTime", endTime);
        return result;
    }


    /**
     * 计算时间
     *
     * @param productPackage
     * @param packageMember
     * @return
     */
    public Map<String, Date> calculateEndDate(ProductPackage productPackage, PackageMember packageMember) {
        Date startTime = null;
        Date endTime = null;
        Calendar calendar = Calendar.getInstance();
        startTime = calendar.getTime(); // 开始时间
        if (packageMember != null) {
            calendar.setTime(packageMember.getEndTime());
        }
        if (productPackage.getUnit().equals(ProductPackage.UNIT_MONTH)) {
            calendar.add(Calendar.MONTH, productPackage.getQuantity());
        } else if (productPackage.getUnit().equals(ProductPackage.UNIT_QUARTER)) {
            calendar.add(Calendar.MONTH, productPackage.getQuantity());
        } else if (productPackage.getUnit().equals(ProductPackage.UNIT_HALF_YEAR)) {
            calendar.add(Calendar.MONTH, productPackage.getQuantity());
        } else if (productPackage.getUnit().equals(ProductPackage.UNIT_YEAR)) {
            calendar.add(Calendar.YEAR, productPackage.getQuantity());
        }
        endTime = calendar.getTime(); // 结束时间

        Map<String, Date> result = Maps.newHashMap();
        result.put("startTime", startTime);
        result.put("endTime", endTime);
        return result;
    }

    /**
     * @Description: 保存或者更新---产品用户
     * @Param:
     * @return:
     * @Author: Hua Qunhao
     * @Date: 2019-05-16-0016
     */
    public String saveOrupdatePackageMember(String memberId, ProductPackage productPackage) {
        PackageMember packageMember = new PackageMember();
        PackageMember packageMember1 = serviceOrderBizService.getPackageMember(productPackage.getId(), memberId);
        packageMember.setPayStatus(1);
        packageMember.setOrderId(null);
        packageMember.setMemberId(memberId);
        packageMember.setLevelId(productPackage.getId());
        packageMember.setStatus(1);
        packageMember.setPackageName(productPackage.getName());
        packageMember.setPrice(productPackage.getPrice());
        packageMember.setPayWay(null);
        packageMember.setQuantity(1);
        Map<String, Date> resultMap = calculateEndDate(productPackage, null);
        Date startTime = resultMap.get("startTime");
        Date endTime = resultMap.get("endTime");
        packageMember.setStartTime(startTime);
        packageMember.setEndTime(endTime);
        if (null != packageMember1) {
            packageMember.setPrice(packageMember1.getPrice());
            packageMember.setGoodsPrice(packageMember1.getGoodsPrice());
            packageMember.setDeductionAmount(packageMember1.getDeductionAmount());
            packageMember.setStartTime(packageMember1.getStartTime());
            packageMember.setEndTime(packageMember1.getEndTime());
        }
        packageMemberService.insert(packageMember);
        return packageMember.getId();
    }

    /**
     * 系统购买
     *
     * @param paymentWay      支付方式
     * @param packageMemberId 套餐id
     * @return
     */
    @Transactional
    public OrderForm systemBuyOrder(Integer paymentWay, String packageMemberId) {
        OrderForm orderForm = null;

        PackageMember packageMember = packageMemberService.get(packageMemberId);
        String packageId = packageMember.getLevelId();
        ProductPackage productPackage = packageService.get(packageId);
        Float newPayment = packageMember.getPrice();

        // 查看这个套餐当天是否产生未支付的订单，如有则返回；否则生成新订单
        String memberId = RealmUtils.getCurrentUser().getId();
        MemberGroup member = memberGroupService.get(memberId);
        MemberGroup adminMember = memberGroupService.findByUserName("admin");

        OrderForm t = new OrderForm();
        t.setMemberId(memberId);
        t.setGoodsId(packageId);
        Map<String, Object> params = Maps.newHashMap();
        Date sd = new Date();
        String std = DateUtils.formatDate(sd, "yyyy-MM-dd") + " 00:00:00";
        params.put("startDate", std);
        String end = DateUtils.formatDate(sd, "yyyy-MM-dd") + " 23:59:59";
        params.put("endDate", end);

        Set<Integer> orderStatus = Sets.newHashSet();
        orderStatus.add(OrderStatus.ORDER_STATUS_OTHER.getCode());
        orderStatus.add(OrderStatus.ORDER_STATUS_TO_BE_PAID.getCode());
        params.put("orderStatus", orderStatus);
        orderForm = orderFormService.getOrderByCondition(t, params);
        if (orderForm != null) {
            //存在支付流水记录，生成新订单
            Boolean flag = queryBizService.checkOrderTradeStatus(newPayment, orderForm);
            if (flag == null || flag || paymentWay != orderForm.getPaymentWay()) {
                orderForm = new OrderForm();
            }
        }

        if (orderForm == null) {
            orderForm = new OrderForm();
        }
        orderForm.setStatus(OrderStatus.ORDER_STATUS_TO_BE_PAID.getCode());
        orderForm.setPayment(newPayment);
        orderForm.setLinkman(member.getRealname());
        orderForm.setPhone(member.getMobile());
        orderForm.setPaymentWay(paymentWay);
        orderForm.setUpdateDate(new Date());
        String title = appendTitle(productPackage, productPackage.getQuantity());
        orderForm.setTitle(title);

        if (StringUtils.isEmpty(orderForm.getId())) {
            orderForm.setCreateBy(memberId);
            orderForm.setUpdateBy(memberId);
            orderForm.setMemberId(memberId);
            orderForm.setGoodsId(packageId);
            orderForm.setInitiatorId(adminMember.getId());
            orderForm.setPayment(newPayment);
            orderForm.setIsPay(YesNoStatus.NO.getValue());
            orderForm.setUnit(1);
            orderForm.setType(OrderType.ORDER__BUY_SYSTEM.getCode());
            orderForm.setStatus(OrderStatus.ORDER_STATUS_TO_BE_PAID.getCode());
            orderFormService.insert(orderForm);

            try {
                OrderFormSubInfo formSubInfo = new OrderFormSubInfo();
                formSubInfo.setOrderId(orderForm.getId());
                if (null != member) {
                    formSubInfo.setAuthorLogo(member.getLogo());
                    formSubInfo.setAuthorName(member.getRealname());
                }
                if (null != adminMember) {
                    formSubInfo.setInitiatorLogo(adminMember.getLogo());
                    formSubInfo.setInitiatorName(adminMember.getRealname());
                }
                orderFormSubInfoService.insert(formSubInfo);
            } catch (Exception e) {
                logger.error("保存订单附属信息异常", e);
            }
        } else {
            orderFormService.update(orderForm);
        }
        //产品用户关系更新orderId
        packageMember.setOrderId(orderForm.getId());
        packageMember.setPayWay(paymentWay);
        packageMemberService.update(packageMember);
        try {
            orderCancelPubulisherService.send(orderForm.getId());
        } catch (Exception e) {
            logger.error("取消超时待支付订单异常", e);
        }
        return orderForm;
    }
}
